package com.heima.search.service.impl;

import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.json.JsonData;
import com.heima.common.dtos.ResponseResult;
import com.heima.model.search.dtos.UserSearchDto;
import com.heima.model.search.vos.SearchArticleVo;
import com.heima.search.pojos.ApAssociateWords;
import com.heima.search.pojos.Baidu;
import com.heima.search.service.ArticleSearchService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.List;

@Slf4j
@Service
public class ArticleSearchServiceImpl implements ArticleSearchService {

    @Resource
    private ElasticsearchClient elasticsearchClient;
    private static final String INDEX_NAME = "app_info_article";
    private static final String BAIDU_HTTP_URL = "https://www.baidu.com/sugrec?prod=pc&wd=";

    /**
     * es文章分页检索
     */
    @Override
    public ResponseResult<List<SearchArticleVo>> search(UserSearchDto dto) throws IOException {
        Query query = this.buildQuery(dto);
        int pageSize = dto.getPageSize();
        int fromIndex = dto.getFromIndex();
        SearchResponse<SearchArticleVo> search = this.elasticsearchClient.search(builder -> builder.index(INDEX_NAME)
                .query(query)
                .size(pageSize)
                .from(fromIndex)
                .sort(s -> s.field(f -> f.field("publishTime")
                        .order(SortOrder.Desc))).highlight(
                        h -> h.fields("title", f -> f.requireFieldMatch(false)
                                .preTags("<font style='color: red; font-size: inherit;'>")
                                .postTags("</font>"))), SearchArticleVo.class);
        List<SearchArticleVo> searchArticleVos = CollStreamUtil.toList(search.hits().hits(), hit -> {
            SearchArticleVo searchArticleVo = hit.source();
            //处理高亮
            assert searchArticleVo != null;
            if (CollUtil.isNotEmpty(hit.highlight())) {
                String hTitle = StrUtil.join("", hit.highlight().get("title"));
                searchArticleVo.setH_title(hTitle);
            } else {
                searchArticleVo.setH_title(searchArticleVo.getTitle());
            }
            return searchArticleVo;
        });

        return ResponseResult.okResult(searchArticleVos);
    }

    private Query buildQuery(UserSearchDto dto) {
        BoolQuery.Builder boolQueryBuilder = new BoolQuery.Builder();

        if (StrUtil.isEmpty(dto.getSearchWords())) {
            //搜索全部
            boolQueryBuilder.must(m -> m.matchAll(ma -> ma));
        } else {
            boolQueryBuilder.must(m -> m.match(mm -> mm.field("all").query(dto.getSearchWords())));
        }

        //添加时间过滤条件
        if (ObjectUtil.isNotEmpty(dto.getMinBehotTime())) {
            boolQueryBuilder.filter(f -> f.range(r -> r.field("publishTime").lt(JsonData.of(dto.getMinBehotTime().getTime()))));
        }

        return new Query.Builder()
                .bool(boolQueryBuilder.build())
                .build();
    }

    @Override
    public ResponseResult<List<ApAssociateWords>> searchSuggest(UserSearchDto dto) {
        if (ObjectUtil.isEmpty(dto)) {
            return null;
        }
        String format = BAIDU_HTTP_URL + dto.getSearchWords();
        String body = HttpRequest.get(format).timeout(3000).execute().body();
        if (ObjectUtil.isEmpty(body)) {
            return null;
        }
        JSONObject entries = JSONUtil.parseObj(body);
        List<Baidu> s = JSONUtil.toList(JSONUtil.toJsonStr(entries.get("g")), Baidu.class);
        List<ApAssociateWords> list = CollStreamUtil.toList(s, l ->
                ApAssociateWords.builder().associateWords(l.getQ()).build()
        );
        return ResponseResult.okResult(list);
    }
}